home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint96sb.zoo / src / fasttext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-21  |  24.1 KB  |  1,275 lines

  1. #include "mint.h"
  2. #include "fasttext.h"
  3.  
  4. #ifdef FASTTEXT
  5.  
  6. #ifdef __GNUC__
  7. #define INLINE inline
  8. #define ITYPE long    /* gcc's optimizer likes 32 bit integers */
  9. #else
  10. #define INLINE
  11. #define ITYPE int
  12. #endif
  13.  
  14. #define CONDEV    (2)
  15.  
  16. static SCREEN *current;
  17.  
  18. static void paint P_((SCREEN *, int, char *)),
  19.      paint8c P_((SCREEN *, int, char *)),
  20.      paint16m P_((SCREEN *, int, char *));
  21.  
  22. INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
  23. INLINE static void flash P_((SCREEN *));
  24. static void normal_putch P_((SCREEN *, int));
  25. static void escy_putch P_((SCREEN *, int));
  26. static void quote_putch P_((SCREEN *, int));
  27.  
  28. static    char *chartab[256];
  29.  
  30. #define MAX_PLANES 8
  31. static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
  32.  
  33. static long scrnsize;
  34.  
  35. short hardscroll;
  36. static char *hardbase, *oldbase;
  37.  
  38. typedef void (*Vfunc) P_((SCREEN *, int));
  39.  
  40. #define base *((char **)0x44eL)
  41. #define escy1 *((short *)0x4acL)
  42.  
  43. static Vfunc state;
  44.  
  45. static short hardline;
  46. static void (*vpaint) P_((SCREEN *, int, char *));
  47.  
  48. void init P_((void));
  49. void hardware_scroll P_((SCREEN *));
  50. INLINE static char *PLACE P_((SCREEN *, int, int));
  51. INLINE static void gotoxy P_((SCREEN *, int, int));
  52. INLINE static void clrline P_((SCREEN *, int));
  53. INLINE static void clear P_((SCREEN *));
  54. INLINE static void clrchar P_((SCREEN *, int, int));
  55. INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
  56. INLINE static void delete_line P_((SCREEN *, int));
  57. INLINE static void insert_line P_((SCREEN *, int));
  58. static void setbgcol P_((SCREEN *, int));
  59. static void setfgcol P_((SCREEN *, int));
  60. static void putesc P_((SCREEN *, int));
  61. static void escy1_putch P_((SCREEN *, int));
  62. INLINE static void put_ch P_((SCREEN *, int));
  63.  
  64. /* routines for flashing the cursor for screen v */
  65. /* flash(v): invert the character currently under the cursor */
  66.  
  67. INLINE static void
  68. flash(v)
  69.     SCREEN *v;
  70. {
  71.     char *place;
  72.     ITYPE i, j, vplanes;
  73.  
  74.     vplanes = v->planes + v->planes;
  75.     place = v->cursaddr;
  76.  
  77.     for (j = v->cheight; j > 0; --j) {
  78.         for (i = 0; i < vplanes; i+=2)
  79.             place[i] = ~place[i];
  80.  
  81.         place += v->planesiz;
  82.     }
  83.     v->curstimer = v->period;
  84. }
  85.  
  86. /* make sure the cursor is off */
  87.  
  88. INLINE
  89. static void
  90. curs_off(v)
  91.     SCREEN *v;
  92. {
  93.     if (v->flags & CURS_ON) {
  94.         if (v->flags & CURS_FSTATE) {
  95.             flash(v);
  96.             v->flags &= ~CURS_FSTATE;
  97.         }
  98.     }
  99. }
  100.  
  101. /* OK, show the cursor again (if appropriate) */
  102.  
  103. INLINE static void
  104. curs_on(v)
  105.     SCREEN *v;
  106. {
  107.     if (v->hidecnt) return;
  108.  
  109.     if (v->flags & CURS_ON) {
  110. #if 0
  111.     /* if the cursor is flashing, we cheat a little and leave it off
  112.      * to be turned on again (if necessary) by the VBL routine
  113.      */
  114.         if (v->flags & CURS_FLASH) {
  115.             v->curstimer = 2;
  116.             return;
  117.         }
  118. #endif
  119.         if (!(v->flags & CURS_FSTATE)) {
  120.             v->flags |= CURS_FSTATE;
  121.             flash(v);
  122.         }
  123.     }
  124. }
  125.  
  126. void
  127. init()
  128. {
  129.     SCREEN *v;
  130.     int i, j;
  131.     char *data, *foo;
  132.     static char chardata[256*16];
  133.  
  134.     foo = lineA0();
  135.     v = (SCREEN *)(foo - 346);
  136.     
  137.     /* Ehem... The screen might be bigger than 32767 bytes.
  138.        Let's do some casting... 
  139.        Erling
  140.     */
  141.     scrnsize = (v->maxy+1)*(long)v->linelen;
  142.     if (hardscroll == -1) {
  143.     /* request for auto-setting */
  144.         hardscroll = v->maxy+1;
  145.     }
  146.     if (hardscroll > 0) {
  147.         if (!hardbase)
  148.             hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
  149.                        & 0xffffff00L);
  150.  
  151.         if (hardbase == 0) {
  152.             ALERT("Insufficient memory for hardware scrolling!");
  153.         } else {
  154.             quickmove(hardbase, base, scrnsize);
  155.             v->cursaddr = v->cursaddr + (hardbase - base);
  156.             oldbase = base;
  157.             base = hardbase;
  158.             Setscreen(hardbase, hardbase, -1);
  159.         }
  160.     }
  161.     hardline = 0;
  162.     if (v->cheight == 8 && v->planes == 2) {
  163.         foo = &chardata[0];
  164.         vpaint = paint8c;
  165.         for (i = 0; i < 256; i++) {
  166.             chartab[i] = foo;
  167.             data = v->fontdata + i;
  168.             for (j = 0; j < 8; j++) {
  169.                 *foo++ = *data;
  170.                 data += v->form_width;
  171.             }
  172.         }
  173.     } else if (v->cheight == 16 && v->planes == 1) {
  174.         foo = &chardata[0];
  175.         vpaint = paint16m;
  176.         for (i = 0; i < 256; i++) {
  177.             chartab[i] = foo;
  178.             data = v->fontdata + i;
  179.             for (j = 0; j < 16; j++) {
  180.                 *foo++ = *data;
  181.                 data += v->form_width;
  182.             }
  183.         }
  184.     }
  185.     else
  186.         vpaint = paint;
  187.  
  188.     if (v->hidecnt == 0) {
  189.     /*
  190.      * make sure the cursor is set up correctly and turned on
  191.      */
  192.         (void)Cursconf(0,0);    /* turn cursor off */
  193.  
  194.         v->flags &= ~CURS_FSTATE;
  195.  
  196.     /* now turn the cursor on the way we like it */
  197.         v->hidecnt = 0;
  198.         curs_on(v);
  199.     } else {
  200.         (void)Cursconf(0,0);
  201.         v->flags &= ~CURS_ON;
  202.         v->hidecnt = 1;
  203.     }
  204.  
  205.     current = v;
  206.     /* setup bgmask and fgmask */
  207.     setbgcol(v, v->bgcol);
  208.     setfgcol(v, v->fgcol);
  209.     state = normal_putch;
  210. }
  211.  
  212. /*
  213.  * PLACE(v, x, y): the address corresponding to the upper left hand corner of
  214.  * the character at position (x,y) on screen v
  215.  */
  216. INLINE static
  217. char *PLACE(v, x, y)
  218.     SCREEN *v;
  219.     int x, y;
  220. {
  221.     char *place;
  222.     int i, j;
  223.  
  224.     place = base + x;
  225.     if (y == v->maxy)
  226.         place += scrnsize - v->linelen;
  227.     else if (y) /* Yo, the screen might be bigger than 32767 bytes...
  228.                Do a cast to long.    Erling. */
  229.         place += (long)y * v->linelen;
  230.  
  231.     if ((j = v->planes) > 1) {
  232.         i = (x & 0xfffe);
  233.         while (--j > 0)
  234.             place += i;
  235.     }
  236.     return place;
  237. }
  238.  
  239. /*
  240.  * paint(v, c, place): put character 'c' at position 'place' on screen
  241.  * v. It is assumed that x, y are proper coordinates!
  242.  * Specialized versions (paint8c and paint16m) of this routine follow;
  243.  * they assume 8 line high characters, medium res. and 16 line/mono,
  244.  * respectively.
  245.  */
  246.  
  247. static void
  248. paint(v, c, place)
  249.     SCREEN *v;
  250.     int c;
  251.     char *place;
  252. {
  253.     char *data, d, doinverse;
  254.     ITYPE j, planecount;
  255.     int vplanes;
  256.     long vform_width, vplanesiz;
  257.  
  258.     vplanes = v->planes;
  259.  
  260.     data = v->fontdata + c;
  261.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  262.     vform_width = v->form_width;
  263.     vplanesiz = v->planesiz;
  264.  
  265.     for (j = v->cheight; j > 0; --j) {
  266.         d = *data ^ doinverse;
  267.         for (planecount = 0; planecount < vplanes; planecount++)
  268.           place[planecount << 1]
  269.             = ((d & (char) fgmask[planecount])
  270.                | (~d & (char) bgmask[planecount]));
  271.         place += vplanesiz;
  272.         data += vform_width;
  273.     }
  274. }
  275.  
  276. static void
  277. paint8c(v, c, place)
  278.     SCREEN *v;
  279.     int c;
  280.     char *place;
  281. {
  282.     char *data;
  283.     char d, doinverse;
  284.     char bg0, bg1, fg0, fg1;
  285.     long vplanesiz;
  286.  
  287.     data = chartab[c];
  288.  
  289.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  290.     vplanesiz = v->planesiz;
  291.     bg0 = bgmask[0];
  292.     bg1 = bgmask[1];
  293.     fg0 = fgmask[0];
  294.     fg1 = fgmask[1];
  295.  
  296.     if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
  297.         /* line 1 */
  298.         d = *data++;
  299.         *place = d;
  300.         place[2] = d;
  301.         place += vplanesiz;
  302.  
  303.         /* line 2 */
  304.         d = *data++;
  305.         *place = d;
  306.         place[2] = d;
  307.         place += vplanesiz;
  308.  
  309.         /* line 3 */
  310.         d = *data++;
  311.         *place = d;
  312.         place[2] = d;
  313.         place += vplanesiz;
  314.  
  315.         /* line 4 */
  316.         d = *data++;
  317.         *place = d;
  318.         place[2] = d;
  319.         place += vplanesiz;
  320.  
  321.         /* line 5 */
  322.         d = *data++;
  323.         *place = d;
  324.         place[2] = d;
  325.         place += vplanesiz;
  326.  
  327.         /* line 6 */
  328.         d = *data++;
  329.         *place = d;
  330.         place[2] = d;
  331.         place += vplanesiz;
  332.  
  333.         /* line 7 */
  334.         d = *data++;
  335.         *place = d;
  336.         place[2] = d;
  337.         place += vplanesiz;
  338.  
  339.         /* line 8 */
  340.         d = *data;
  341.         *place = d;
  342.         place[2] = d;
  343.     } else {
  344.         /* line 1 */
  345.         d = *data++ ^ doinverse;
  346.         *place = ((d & fg0) | (~d & bg0));
  347.         place[2] = ((d & fg1) | (~d & bg1));
  348.         place += vplanesiz;
  349.  
  350.         /* line 2 */
  351.         d = *data++ ^ doinverse;
  352.         *place = ((d & fg0) | (~d & bg0));
  353.         place[2] = ((d & fg1) | (~d & bg1));
  354.         place += vplanesiz;
  355.  
  356.         /* line 3 */
  357.         d = *data++ ^ doinverse;
  358.         *place = ((d & fg0) | (~d & bg0));
  359.         place[2] = ((d & fg1) | (~d & bg1));
  360.         place += vplanesiz;
  361.  
  362.         /* line 4 */
  363.         d = *data++ ^ doinverse;
  364.         *place = ((d & fg0) | (~d & bg0));
  365.         place[2] = ((d & fg1) | (~d & bg1));
  366.         place += vplanesiz;
  367.  
  368.         /* line 5 */
  369.         d = *data++ ^ doinverse;
  370.         *place = ((d & fg0) | (~d & bg0));
  371.         place[2] = ((d & fg1) | (~d & bg1));
  372.         place += vplanesiz;
  373.  
  374.         /* line 6 */
  375.         d = *data++ ^ doinverse;
  376.         *place = ((d & fg0) | (~d & bg0));
  377.         place[2] = ((d & fg1) | (~d & bg1));
  378.         place += vplanesiz;
  379.  
  380.         /* line 7 */
  381.         d = *data++ ^ doinverse;
  382.         *place = ((d & fg0) | (~d & bg0));
  383.         place[2] = ((d & fg1) | (~d & bg1));
  384.         place += vplanesiz;
  385.  
  386.         /* line 8 */
  387.         d = *data ^ doinverse;
  388.         *place = ((d & fg0) | (~d & bg0));
  389.         place[2] = ((d & fg1) | (~d & bg1));
  390.     }
  391. }
  392.  
  393. static void
  394. paint16m(v, c, place)
  395.     SCREEN *v;
  396.     int c;
  397.     char *place;
  398. {
  399.     char *data;
  400.     char d, doinverse;
  401.     long vplanesiz;
  402.  
  403.     data = chartab[c];
  404.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  405.     doinverse ^= bgmask[0];
  406.     vplanesiz = v->planesiz;
  407.  
  408.     if (bgmask[0] == fgmask[0])
  409.       {
  410.         /* fgcol and bgcol are the same -- easy */
  411.         d = (char) bgmask[0];
  412.         *place = d;
  413.         place += vplanesiz;
  414.         *place = d;
  415.         place += vplanesiz;
  416.         *place = d;
  417.         place += vplanesiz;
  418.         *place = d;
  419.         place += vplanesiz;
  420.         *place = d;
  421.         place += vplanesiz;
  422.         *place = d;
  423.         place += vplanesiz;
  424.         *place = d;
  425.         place += vplanesiz;
  426.         *place = d;
  427.         place += vplanesiz;
  428.         *place = d;
  429.         place += vplanesiz;
  430.         *place = d;
  431.         place += vplanesiz;
  432.         *place = d;
  433.         place += vplanesiz;
  434.         *place = d;
  435.         place += vplanesiz;
  436.         *place = d;
  437.         place += vplanesiz;
  438.         *place = d;
  439.         place += vplanesiz;
  440.         *place = d;
  441.         place += vplanesiz;
  442.         *place = d;
  443.       }
  444.     else if (!doinverse) {
  445.         /* line 1 */
  446.         d = *data++;
  447.         *place = d;
  448.         place += vplanesiz;
  449.  
  450.         /* line 2 */
  451.         d = *data++;
  452.         *place = d;
  453.         place += vplanesiz;
  454.  
  455.         /* line 3 */
  456.         d = *data++;
  457.         *place = d;
  458.         place += vplanesiz;
  459.  
  460.         /* line 4 */
  461.         d = *data++;
  462.         *place = d;
  463.         place += vplanesiz;
  464.  
  465.         /* line 5 */
  466.         d = *data++;
  467.         *place = d;
  468.         place += vplanesiz;
  469.  
  470.         /* line 6 */
  471.         d = *data++;
  472.         *place = d;
  473.         place += vplanesiz;
  474.  
  475.         /* line 7 */
  476.         d = *data++;
  477.         *place = d;
  478.         place += vplanesiz;
  479.  
  480.         /* line 8 */
  481.         d = *data++;
  482.         *place = d;
  483.         place += vplanesiz;
  484.  
  485.         /* line 9 */
  486.         d = *data++;
  487.         *place = d;
  488.         place += vplanesiz;
  489.  
  490.         /* line 10 */
  491.         d = *data++;
  492.         *place = d;
  493.         place += vplanesiz;
  494.  
  495.         /* line 11 */
  496.         d = *data++;
  497.         *place = d;
  498.         place += vplanesiz;
  499.  
  500.         /* line 12 */
  501.         d = *data++;
  502.         *place = d;
  503.         place += vplanesiz;
  504.  
  505.         /* line 13 */
  506.         d = *data++;
  507.         *place = d;
  508.         place += vplanesiz;
  509.  
  510.         /* line 14 */
  511.         d = *data++;
  512.         *place = d;
  513.         place += vplanesiz;
  514.  
  515.         /* line 15 */
  516.         d = *data++;
  517.         *place = d;
  518.         place += vplanesiz;
  519.  
  520.         /* line 16 */
  521.         d = *data;
  522.         *place = d;
  523.     } else {
  524.         /* line 1 */
  525.         d = ~*data++;
  526.         *place = d;
  527.         place += vplanesiz;
  528.  
  529.         /* line 2 */
  530.         d = ~*data++;
  531.         *place = d;
  532.         place += vplanesiz;
  533.  
  534.         /* line 3 */
  535.         d = ~*data++;
  536.         *place = d;
  537.         place += vplanesiz;
  538.  
  539.         /* line 4 */
  540.         d = ~*data++;
  541.         *place = d;
  542.         place += vplanesiz;
  543.  
  544.         /* line 5 */
  545.         d = ~*data++;
  546.         *place = d;
  547.         place += vplanesiz;
  548.  
  549.         /* line 6 */
  550.         d = ~*data++;
  551.         *place = d;
  552.         place += vplanesiz;
  553.  
  554.         /* line 7 */
  555.         d = ~*data++;
  556.         *place = d;
  557.         place += vplanesiz;
  558.  
  559.         /* line 8 */
  560.         d = ~*data++;
  561.         *place = d;
  562.         place += vplanesiz;
  563.  
  564.         /* line 9 */
  565.         d = ~*data++;
  566.         *place = d;
  567.         place += vplanesiz;
  568.  
  569.         /* line 10 */
  570.         d = ~*data++;
  571.         *place = d;
  572.         place += vplanesiz;
  573.  
  574.         /* line 11 */
  575.         d = ~*data++;
  576.         *place = d;
  577.         place += vplanesiz;
  578.  
  579.         /* line 12 */
  580.         d = ~*data++;
  581.         *place = d;
  582.         place += vplanesiz;
  583.  
  584.         /* line 13 */
  585.         d = ~*data++;
  586.         *place = d;
  587.         place += vplanesiz;
  588.  
  589.         /* line 14 */
  590.         d = ~*data++;
  591.         *place = d;
  592.         place += vplanesiz;
  593.  
  594.         /* line 15 */
  595.         d = ~*data++;
  596.         *place = d;
  597.         place += vplanesiz;
  598.  
  599.         /* line 16 */
  600.         d = ~*data;
  601.         *place = d;
  602.     }
  603. }
  604.  
  605. /*
  606.  * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
  607.  * makes sure that (x, y) will be legal
  608.  */
  609.  
  610. INLINE static void
  611. gotoxy(v, x, y)
  612.     SCREEN *v;
  613.     int x, y;
  614. {
  615.     if (x > v->maxx) x = v->maxx;
  616.     else if (x < 0) x = 0;
  617.     if (y > v->maxy) y = v->maxy;
  618.     else if (y < 0) y = 0;
  619.  
  620.     v->cx = x;
  621.     v->cy = y;
  622.     v->cursaddr = PLACE(v, x, y);
  623. }
  624.  
  625. /*
  626.  * clrline(v, r): clear line r of screen v
  627.  */
  628.  
  629. INLINE static void
  630. clrline(v, r)
  631.     SCREEN *v;
  632.     int r;
  633. {
  634.     int *dst, *m;
  635.     long nwords;
  636.     int i, vplanes;
  637.  
  638.     /* Hey, again the screen might be bigger than 32767 bytes.
  639.        Do another cast... */
  640.     dst = (int *)(base + ((long)r * v->linelen));
  641.     if (v->bgcol == 0)
  642.       zero((char *)dst, v->linelen);
  643.     else
  644.       {
  645.         /* do it the hard way */
  646.         vplanes = v->planes;
  647.         for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
  648.           {
  649.         m = bgmask;
  650.         for (i = 0; i < vplanes; i++)
  651.           *dst++ = *m++;
  652.           }
  653.       }
  654. }
  655.     
  656. /*
  657.  * clear(v): clear the whole screen v
  658.  */
  659.  
  660. INLINE static void
  661. clear(v)
  662.     SCREEN *v;
  663. {
  664.     int i, vplanes;
  665.     int *dst, *m;
  666.     long nwords;
  667.  
  668.     if (v->bgcol == 0)
  669.       zero(base, scrnsize);
  670.     else
  671.       {
  672.         /* do it the hard way */
  673.         dst = (int *) base;
  674.         vplanes = v->planes;
  675.         for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
  676.           {
  677.         m = bgmask;
  678.         for (i = 0; i < vplanes; i++)
  679.           *dst++ = *m++;
  680.           }
  681.       }
  682. }
  683.  
  684. /*
  685.  * clrchar(v, x, y): clear the (x,y) position on screen v
  686.  */
  687.  
  688. INLINE static void
  689. clrchar(v, x, y)
  690.     SCREEN *v;
  691.     int x, y;
  692. {
  693.     int i, j, vplanes;
  694.     char *place;
  695.     int *m;
  696.  
  697.     vplanes = v->planes + v->planes;
  698.  
  699.     place = PLACE(v, x, y);
  700.  
  701.     for (j = v->cheight; j > 0; --j) {
  702.         m = bgmask;
  703.         for (i = 0; i < vplanes; i += 2)
  704.             place[i] = (char) *m++;
  705.         place += v->planesiz;
  706.     }
  707. }
  708.  
  709. /*
  710.  * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
  711.  * position (x2, y2) inclusive. It is assumed that y2 >= y1.
  712.  */
  713.  
  714. INLINE static void
  715. clrfrom(v, x1, y1, x2, y2)
  716.     SCREEN *v;
  717.     int x1,y1,x2,y2;
  718. {
  719.     int i;
  720.  
  721.     for (i = x1; i <= v->maxx; i++)
  722.         clrchar(v, i, y1);
  723.     if (y2 > y1) {
  724.         for (i = 0; i <= x2; i++)
  725.             clrchar(v, i, y2);
  726.         for (i = y1+1; i < y2; i++)
  727.             clrline(v, i);
  728.     }
  729. }
  730.  
  731. /*
  732.  * scroll a screen in hardware; if we still have hardware scrolling lines left,
  733.  * just move the physical screen base, otherwise copy the screen back to the
  734.  * hardware base and start over
  735.  */
  736. void
  737. hardware_scroll(v)
  738.     SCREEN *v;
  739. {
  740.  
  741.     ++hardline;
  742.     if (hardline < hardscroll) { /* just move the screen */
  743.         base += v->linelen;
  744.         v->cursaddr = PLACE(v, v->cx, v->cy);
  745.         Setscreen(base, base, -1);
  746.     }
  747.     else {
  748.         hardline = 0;
  749.         quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
  750.         base = hardbase;
  751.         v->cursaddr = PLACE(v, v->cx, v->cy);
  752.         Setscreen(hardbase, hardbase, -1);
  753.     }
  754. }
  755.  
  756. /*
  757.  * delete_line(v, r): delete line r of screen v. The screen below this
  758.  * line is scrolled up, and the bottom line is cleared.
  759.  */
  760.  
  761. #define scroll(v) delete_line(v, 0)
  762.  
  763. INLINE static void
  764. delete_line(v, r)
  765.     SCREEN *v;
  766.     int r;
  767. {
  768.     long *src, *dst, nbytes;
  769.  
  770.     if (r == 0) {
  771.         if (hardbase) {
  772.             hardware_scroll(v);
  773.             clrline(v, v->maxy);
  774.             return;
  775.         }
  776.         nbytes = scrnsize - v->linelen;
  777.     }
  778.     else
  779.         nbytes = (long)v->linelen * (v->maxy - r);
  780.  
  781.     /* Sheeze, how many times do we really have to cast... 
  782.        Erling.    
  783.     */
  784.  
  785.     dst = (long *)(base + ((long)r * v->linelen));
  786.     src = (long *)( ((long)dst) + v->linelen);
  787.  
  788.     quickmove(dst, src, nbytes);
  789.  
  790. /* clear the last line */
  791.     clrline(v, v->maxy);
  792. }
  793.  
  794. /*
  795.  * insert_line(v, r): scroll all of the screen starting at line r down,
  796.  * and then clear line r.
  797.  */
  798.  
  799. INLINE static void
  800. insert_line(v, r)
  801.     SCREEN *v;
  802.     int r;
  803. {
  804.     long *src, *dst;
  805.     int i, limit;
  806.  
  807.     limit = v->maxy;
  808.     for (i = limit-1; i >= r ; --i) {
  809.     /* move line i to line i+1 */
  810.     /* AND do some casting to support big screens.
  811.        Erling
  812.     */
  813.         src = (long *)(base + ((long)i * v->linelen));
  814.         dst = (long *)(base + ((i+1)*(long)v->linelen));
  815.         quickmove(dst, src, v->linelen);
  816.     }
  817.  
  818. /* clear line r */
  819.     clrline(v, r);
  820. }
  821.  
  822. /*
  823.  * special states for handling ESC b x and ESC c x. Note that for now,
  824.  * color is ignored.
  825.  */
  826.  
  827. static void
  828. setbgcol(v, c)
  829.     SCREEN *v;
  830.     int c;
  831. {
  832.     int i;
  833.  
  834.     v->bgcol = c & ((1 << v->planes)-1);
  835.     for (i = 0; i < v->planes; i++)
  836.         bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
  837.     state = normal_putch;
  838. }
  839.  
  840. static void
  841. setfgcol(v, c)
  842.     SCREEN *v;
  843.     int c;
  844. {
  845.     int i;
  846.  
  847.     v->fgcol = c & ((1 << v->planes)-1);
  848.     for (i = 0; i < v->planes; i++)
  849.         fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
  850.     state = normal_putch;
  851. }
  852.  
  853. static void
  854. quote_putch(v, c)
  855.     SCREEN *v;
  856.     int c;
  857. {
  858.     (*vpaint)(v, c, v->cursaddr);
  859.     state = normal_putch;
  860. }
  861.  
  862. /*
  863.  * putesc(v, c): handle the control sequence ESC c
  864.  */
  865.  
  866. static void
  867. putesc(v, c)
  868.     SCREEN *v;
  869.     int c;
  870. {
  871.     int cx, cy;
  872.  
  873.     cx = v->cx; cy = v->cy;
  874.  
  875.     switch (c) {
  876.     case 'A':        /* cursor up */
  877.         gotoxy(v, cx, cy-1);
  878.         break;
  879.     case 'B':        /* cursor down */
  880.         gotoxy(v, cx, cy+1);
  881.         break;
  882.     case 'C':        /* cursor right */
  883.         gotoxy(v, cx+1, cy);
  884.         break;
  885.     case 'D':        /* cursor left */
  886.         gotoxy(v, cx-1, cy);
  887.         break;
  888.     case 'E':        /* clear home */
  889.         clear(v);
  890.         /* fall through... */
  891.     case 'H':        /* cursor home */
  892.         gotoxy(v, 0, 0);
  893.         break;
  894.     case 'I':        /* cursor up, insert line */
  895.         if (cy == 0) {
  896.             insert_line(v, 0);
  897.         }
  898.         else
  899.             gotoxy(v, cx, cy-1);
  900.         break;
  901.     case 'J':        /* clear below cursor */
  902.         clrfrom(v, cx, cy, v->maxx, v->maxy);
  903.         break;
  904.     case 'K':        /* clear remainder of line */
  905.         clrfrom(v, cx, cy, v->maxx, cy);
  906.         break;
  907.     case 'L':        /* insert a line */
  908.         gotoxy(v, 0, cy);
  909.         insert_line(v, cy);
  910.         break;
  911.     case 'M':        /* delete line */
  912.         gotoxy(v, 0, cy);
  913.         delete_line(v, cy);
  914.         break;
  915.     case 'Q':        /* quote-next-char */
  916.         state = quote_putch;
  917.         return;
  918.     case 'Y':
  919.         state = escy_putch;
  920.         return;        /* YES, this should be 'return' */
  921.  
  922.     case 'b':
  923.         state = setfgcol;
  924.         return;
  925.     case 'c':
  926.         state = setbgcol;
  927.         return;
  928.     case 'd':        /* clear to cursor position */
  929.         clrfrom(v, 0, 0, cx, cy);
  930.         break;
  931.     case 'e':        /* enable cursor */
  932.         v->flags |= CURS_ON;
  933.         v->hidecnt = 1;    /* so --v->hidecnt shows the cursor */
  934.         break;
  935.     case 'f':        /* cursor off */
  936.         v->hidecnt++;
  937.         v->flags &= ~CURS_ON;
  938.         break;
  939.     case 'j':        /* save cursor position */
  940.         v->savex = v->cx;
  941.         v->savey = v->cy;
  942.         break;
  943.     case 'k':        /* restore saved position */
  944.         gotoxy(v, v->savex, v->savey);
  945.         break;
  946.     case 'l':        /* clear line */
  947.         gotoxy(v, 0, cy);
  948.         clrline(v, cy);
  949.         break;
  950.     case 'o':        /* clear from start of line to cursor */
  951.         clrfrom(v, 0, cy, cx, cy);
  952.         break;
  953.     case 'p':        /* reverse video on */
  954.         v->flags |= FINVERSE;
  955.         break;
  956.     case 'q':        /* reverse video off */
  957.         v->flags &= ~FINVERSE;
  958.         break;
  959.     case 'v':        /* wrap on */
  960.         v->flags |= FWRAP;
  961.         break;
  962.     case 'w':
  963.         v->flags &= ~FWRAP;
  964.         break;
  965.     }
  966.     state = normal_putch;
  967. }
  968.  
  969. /*
  970.  * escy1_putch(v, c): for when an ESC Y + char has been seen
  971.  */
  972. static void
  973. escy1_putch(v, c)
  974.     SCREEN *v;
  975.     int c;
  976. {
  977.     gotoxy(v, c - ' ', escy1 - ' ');
  978.     state = normal_putch;
  979. }
  980.  
  981. /*
  982.  * escy_putch(v, c): for when an ESC Y has been seen
  983.  */
  984. static void
  985. escy_putch(v, c)
  986.     SCREEN *v;
  987.     int c;
  988. {
  989.     UNUSED(v);
  990.     escy1 = c;
  991.     state = escy1_putch;
  992. }
  993.  
  994. /*
  995.  * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
  996.  * for when no escape, etc. is active
  997.  */
  998.  
  999. static void
  1000. normal_putch(v, c)
  1001.     SCREEN *v;
  1002.     int c;
  1003. {
  1004. /* control characters */
  1005.     if (c < ' ') {
  1006.         switch (c) {
  1007.         case '\r':
  1008.             gotoxy(v, 0, v->cy);
  1009.             return;
  1010.         case '\n':
  1011.             if (v->cy == v->maxy) {
  1012.                 scroll(v);
  1013.             }
  1014.             else
  1015.                 gotoxy(v, v->cx, v->cy+1);
  1016.             return;
  1017.         case '\b':
  1018.             gotoxy(v, v->cx-1, v->cy);
  1019.             return;
  1020.         case '\007':        /* BELL */
  1021.             (void)bconout(CONDEV, 7);
  1022.             return;
  1023.         case '\033':        /* ESC */
  1024.             state = putesc;
  1025.             return;
  1026.         case '\t':
  1027.             gotoxy(v, (v->cx + 8) & ~7, v->cy);
  1028.             return;
  1029.         default:
  1030.             return;
  1031.         }
  1032.     }
  1033.  
  1034.     (*vpaint)(v, c, v->cursaddr);
  1035.     v->cx++;
  1036.     if (v->cx > v->maxx) {
  1037.         if (v->flags & FWRAP) {
  1038.             v->cx = 0;
  1039.             normal_putch(v, '\n');
  1040.             v->cursaddr = PLACE(v, v->cx, v->cy);
  1041.         } else {
  1042.             v->cx = v->maxx;
  1043.         }
  1044.     } else {
  1045. #if 0
  1046.         v->cursaddr = PLACE(v, v->cx, v->cy);
  1047. #else
  1048.         v->cursaddr++;
  1049.         if ( (v->cx & 1) == 0 && v->planes > 1) { /* new word */
  1050.             short skipwords = v->planes - 1;
  1051.             v->cursaddr += skipwords+skipwords;
  1052.         }
  1053. #endif
  1054.     }
  1055. }
  1056.  
  1057. INLINE static void
  1058. put_ch(v, c)
  1059.     SCREEN *v;
  1060.     int c;
  1061. {
  1062.     (*state)(v, c & 0x00ff);
  1063. }
  1064.  
  1065. static long ARGS_ON_STACK screen_open    P_((FILEPTR *f));
  1066. static long ARGS_ON_STACK screen_read    P_((FILEPTR *f, char *buf, long nbytes));
  1067. static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
  1068. static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
  1069. static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
  1070. static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
  1071. static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
  1072. static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
  1073.  
  1074. extern long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  1075.  
  1076. DEVDRV screen_device = {
  1077.     screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
  1078.     null_datime, screen_close, screen_select, screen_unselect
  1079. };
  1080.  
  1081. static long ARGS_ON_STACK 
  1082. screen_open(f)
  1083.     FILEPTR *f;
  1084. {
  1085.  
  1086.     if (!current) {
  1087.         init();
  1088.     } else
  1089.         return EACCDN;        /* screen in use */
  1090.  
  1091.     f->flags |= O_TTY;
  1092.     return 0;
  1093. }
  1094.  
  1095. static long ARGS_ON_STACK 
  1096. screen_close(f, pid)
  1097.     FILEPTR *f;
  1098.     int pid;
  1099. {
  1100.     UNUSED(pid);
  1101.  
  1102.     if (f->links <= 0) {
  1103.         if (hardbase) {
  1104.             quickmove(oldbase, base, scrnsize);
  1105.             base = oldbase;
  1106.             Setscreen(oldbase, oldbase, -1);
  1107.         }
  1108.         current = 0;
  1109.     }
  1110.     return 0;
  1111. }
  1112.  
  1113. static long ARGS_ON_STACK 
  1114. screen_write(f, buf, bytes)
  1115.     FILEPTR *f; const char *buf; long bytes;
  1116. {
  1117.     SCREEN *v = current;
  1118.     long *r;
  1119.     long ret = 0;
  1120.     int c;
  1121.  
  1122.     UNUSED(f);
  1123.  
  1124.     (void)checkkeys();
  1125.     v->hidecnt++;
  1126.     v->flags |= CURS_UPD;        /* for TOS 1.0 */
  1127.     curs_off(v);
  1128.     r = (long *)buf;
  1129.     while (bytes > 0) {
  1130.         c = (int) *r++;
  1131.         put_ch(v, c);
  1132.         bytes -= 4; ret+= 4;
  1133.     }
  1134.     if (v->hidecnt > 0)
  1135.         --v->hidecnt;
  1136.     else
  1137.         v->hidecnt = 0;
  1138.     curs_on(v);
  1139.     v->flags &= ~CURS_UPD;
  1140.     return ret;
  1141. }
  1142.  
  1143. static long ARGS_ON_STACK 
  1144. screen_read(f, buf, bytes)
  1145.     FILEPTR *f; char *buf; long bytes;
  1146. {
  1147.     long *r, ret = 0;
  1148.  
  1149.     r = (long *)buf;
  1150.  
  1151.     while (bytes > 0) {
  1152.         if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
  1153.             break;
  1154.         *r++ = bconin(CONDEV) & 0x7fffffffL;
  1155.         bytes -= 4; ret += 4;
  1156.     }
  1157.     return ret;
  1158. }
  1159.  
  1160. static long ARGS_ON_STACK 
  1161. screen_lseek(f, where, whence)
  1162.     FILEPTR *f;
  1163.     long where;
  1164.     int whence;
  1165. {
  1166. /* terminals always are at position 0 */
  1167.     UNUSED(f); UNUSED(where);
  1168.     UNUSED(whence);
  1169.     return 0;
  1170. }
  1171.  
  1172. static long ARGS_ON_STACK 
  1173. screen_ioctl(f, mode, buf)
  1174.     FILEPTR *f; int mode; void *buf;
  1175. {
  1176.     long *r = (long *)buf;
  1177.     struct winsize *w;
  1178.  
  1179.     UNUSED(f);
  1180.  
  1181.     if (mode == FIONREAD) {
  1182.         if (bconstat(CONDEV))
  1183.             *r = 1;
  1184.         else
  1185.             *r = 0;
  1186.     }
  1187.     else if (mode == FIONWRITE) {
  1188.             *r = 1;
  1189.     }
  1190.     else if (mode == TIOCFLUSH) {
  1191. /* BUG: this should flush the input/output buffers */
  1192.         return 0;
  1193.     }
  1194.     else if (mode == TIOCGWINSZ) {
  1195.         w = (struct winsize *)buf;
  1196.         w->ws_row = current->maxy+1;
  1197.         w->ws_col = current->maxx+1;
  1198.     }
  1199.     else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
  1200.         SCREEN *v = current;
  1201.         switch(mode) {
  1202.         case TCURSOFF:
  1203.             curs_off(v);
  1204.             v->hidecnt++;
  1205.             v->flags &= ~CURS_ON;
  1206.             break;
  1207.         case TCURSON:
  1208.             v->flags |= CURS_ON;
  1209.             v->hidecnt = 0;
  1210.             curs_on(v);
  1211.             break;
  1212.         case TCURSBLINK:
  1213.             curs_off(v);
  1214.             v->flags |= CURS_FLASH;
  1215.             curs_on(v);
  1216.             break;
  1217.         case TCURSSTEADY:
  1218.             curs_off(v);
  1219.             v->flags &= ~CURS_FLASH;
  1220.             curs_on(v);
  1221.             break;
  1222.         case TCURSSRATE:
  1223.             v->period = *((short *)buf);
  1224.             break;
  1225.         case TCURSGRATE:
  1226.             return v->period;
  1227.         }
  1228.     } else
  1229.         return EINVFN;
  1230.  
  1231.     return 0;
  1232. }
  1233.  
  1234. static long ARGS_ON_STACK 
  1235. screen_select(f, p, mode)
  1236.     FILEPTR *f; long p; int mode;
  1237. {
  1238.     struct tty *tty = (struct tty *)f->devinfo;
  1239.     int dev = CONDEV;
  1240.  
  1241.     if (mode == O_RDONLY) {
  1242.         if (bconstat(dev)) {
  1243.             return 1;
  1244.         }
  1245.         if (tty) {
  1246.         /* avoid collisions with other processes */
  1247.             if (!tty->rsel)
  1248.                 tty->rsel = p;
  1249.         }
  1250.         return 0;
  1251.     } else if (mode == O_WRONLY) {
  1252.         return 1;
  1253.     }
  1254.     /* default -- we don't know this mode, return 0 */
  1255.     return 0;
  1256. }
  1257.  
  1258. static void ARGS_ON_STACK 
  1259. screen_unselect(f, p, mode)
  1260.     FILEPTR *f;
  1261.     long p;
  1262.     int mode;
  1263. {
  1264.     struct tty *tty = (struct tty *)f->devinfo;
  1265.  
  1266.     if (tty) {
  1267.         if (mode == O_RDONLY && tty->rsel == p)
  1268.             tty->rsel = 0;
  1269.         else if (mode == O_WRONLY && tty->wsel == p)
  1270.             tty->wsel = 0;
  1271.     }
  1272. }
  1273.  
  1274. #endif /* FASTTEXT */
  1275.